发布于 

Cosmic Cleaner [计算几何]

Cosmic Cleaner [计算几何]

Wannafly Day 1 H

题目来源:comet OJ

一道裸的三维计算几何题,也是当天当时唯一做出来的一道题。

分析

这道题的题意十分好分析,其实就是求一个大球和\(n\)个小球的交的总和。对于球的交,我们可以先判断它们是否相交,若相交直接套用公式即可,否则要判断一下特殊情况。

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

#include <iostream>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <cstring>

using namespace std;

const double PI = acos(-1.0);

struct Point
{
double x, y, z;

Point() {}

Point(double x, double y, double z)
:x(x), y(y), z(z) {}

Point operator - (const Point &tmp) const
{
return Point(this->x - tmp.x, this->y - tmp.y, this->z - tmp.z);
}

Point operator + (const Point &tmp) const
{
return Point(this->x + tmp.x, this->y + tmp.y, this->z + tmp.z);
}

Point operator * (const double &k) const
{
return Point(this->x * k, this->y * k, this->z * k);
}

Point operator / (const double &k) const
{
return Point(this->x / k, this->y / k, this->z / k);
}

double operator * (const Point &tmp) const
{
return this->x * tmp.x + this->y * tmp.y + this->z * tmp.z;
}
};

double dist(Point a, Point b)
{
return sqrt( (a - b) * (a - b) );
}

struct Sphere
{
Point center;
double r;

Sphere() {};

Sphere(Point center, double r)
:center(center), r(r) {}
}a[110];

double SphereInterV(Sphere a, Sphere b)
{
double d = dist(a.center, b.center);
double l1 = ( (a.r * a.r - b.r * b.r) / d + d) / 2.0;

double l2 = d - l1;
double x1 = a.r - l1, x2 = b.r - l2;

double v1 = PI * x1 * x1 * (a.r - x1 / 3.0);
double v2 = PI * x2 * x2 * (b.r - x2 / 3.0);

double v = v1 + v2;
return v;
}

int main()
{
ios::sync_with_stdio(false);

int T;
cin >> T;

for (int cas = 1; cas<=T; cas++)
{
memset(a, 0, sizeof(a));

int n;
cin >> n;

for (int i = 1; i<=n; i++)
{
int x, y, z, r;
cin >> x >> y >> z >> r;

a[i] = Sphere(Point(x, y, z), r);
}

int x, y, z, r;
cin >> x >> y >> z >> r;
Sphere clear(Point(x, y, z), r);

double ans = 0;
for (int i = 1; i<=n; i++)
{
if ( dist(clear.center, a[i].center) + a[i].r <= clear.r)
ans += 4.0 / 3 * PI * a[i].r * a[i].r * a[i].r;
else if ( dist(clear.center, a[i].center) < a[i].r + clear.r)
ans += SphereInterV(clear, a[i]);
}

cout << fixed;
cout << "Case #" << cas << ": " << setprecision(20) << ans << endl;
}
}

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 [@Songer](https://blog.songer.xyz/) 创建,使用 Stellar 作为主题。